import dao.IFileDAO;
import dao.IUserDAO;
import dao.impl.FileDAOImpl;
import dao.impl.UserDAOImpl;
import pojo.FileItem;
import pojo.User;
import utils.FileUtils;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.SimpleTimeZone;

import static utils.FileUtils.*;

/**
 * 网盘服务器
 */
public class ServerV2 {

    private static IUserDAO userDAO=new UserDAOImpl();
    private static IFileDAO fileDAO=new FileDAOImpl();
    /**
     * 处理文件的查询
     */
    public void handleListFiles(DataInputStream dataInputStream,DataOutputStream dataOutputStream) throws IOException {
        //接受用户的id
        long userId = dataInputStream.readLong();
        try {
            List<FileItem> fileItems = fileDAO.selectFileItemByUserId(userId);
            //获得文件集合的JSON
            String json = listToJSON(fileItems);
            //发送给客户端
            dataOutputStream.writeUTF(json);
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     *处理文件上传
     *
     */
    public static void handleUpload(DataInputStream dataInputStream,DataOutputStream dataOutputStream) throws IOException{
        //接收文件名
        String fileName= dataInputStream.readUTF();
        if("error".equals(fileName)){
            System.out.println("客户端文件错误");
            return;
        }
        //接受用户ID
        long userId = dataInputStream.readLong();
        //查询用户名
        try {
            User user = userDAO.selectUserById(userId);
            //判断该用户的上传目录是否存在，若不存在就创建
            File file = new File(UPLOAD_DIR+"\\"+user.getUsername());
            if(!file.exists()){
                file.mkdirs();
            }
            //创建文件输出流
            File upLoadFile = new File(UPLOAD_DIR+
                    "\\"+user.getUsername()+"\\"+fileName);
            FileOutputStream fileOutputStream = new FileOutputStream(upLoadFile);
            //从客户端输入流读取字节，写入到本地文件中
            FileUtils.io(dataInputStream,fileOutputStream);
            //判断该用户的文件是否存在于数据库中
            FileItem fileItem = fileDAO.selectFileItemByUserIdAndFilename(userId, fileName);
            String time = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date());
            //不存在就插入新的数据
            if(fileItem==null) {
                fileItem = new FileItem(0l, upLoadFile.getName(), upLoadFile.getAbsolutePath(), upLoadFile.length()
                        , userId,0,time );
                fileDAO.insertFileItem(fileItem);
            }else{
                //存在就更新长度和上传时间
                fileItem.setLength(upLoadFile.length());
                fileItem.setCrate_time(time);
                fileDAO.updateFileItem(fileItem);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 处理文件下载
     *
     */
    public static void handleDownload(DataInputStream dataInputStream,DataOutputStream dataOutputStream) throws IOException {
        //接受文件名
        Long fileId = dataInputStream.readLong();
        //查询文件信息
        try {
            FileItem fileItem = fileDAO.selectFileItemById(fileId);
            File file = new File(fileItem.getPath());
            //判断服务器上是否存在该文件
            if(file.exists()){
                //如果存在，就发送文件名给客户端
                dataOutputStream.writeUTF(file.getName());
                //读取本地磁盘文件，发送给客户端
                FileInputStream fileInputStream = new FileInputStream(file);
                FileUtils.io(fileInputStream,dataOutputStream);
            }else{
                //不存在就发送错误信息
                dataOutputStream.writeUTF("error");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     *
     * @param dataInputStream
     * @param dataOutputStream
     * @throws IOException
     */
    public static void handleDelete(DataInputStream dataInputStream,DataOutputStream dataOutputStream) throws IOException {
        //接受文件名
        Long fileId = dataInputStream.readLong();
        //查询文件信息
        try {
            FileItem fileItem = fileDAO.selectFileItemById(fileId);
            File file = new File(fileItem.getPath());
            //判断服务器上是否存在该文件
            if(file.exists()){
                //如果存在，就发送文件名给客户端
                dataOutputStream.writeUTF(file.getName());
                //删除数据库和磁盘上的文件
                fileDAO.deleteFileItem(fileId);
                file.delete();

            }else{
                //不存在就发送错误信息
                dataOutputStream.writeUTF("error");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void handleLogin(DataInputStream dataInputStream,DataOutputStream dataOutputStream) throws IOException {
        //接受账号和密码
        String username=dataInputStream.readUTF();
        String password=dataInputStream.readUTF();
        //在数据库中登录验证
        try{
            User user = userDAO.login(username, password);
            if(user==null){
                //用户不存在返回-1
                dataOutputStream.writeLong(-1l);
                return;
            }
            //返回用户ID给客户端
            dataOutputStream.writeLong(user.getId());
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }

    /**
     * 启动服务器
     */
    public void star(){
        System.out.println("网盘服务器启动了");
        //创建服务器Socket
        try(ServerSocket serverSocket = new ServerSocket(PORT)){
            //接收客户端的连接
            for(;;){
                 Socket socket = serverSocket.accept();
                 //获取IO流
                try(DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                    DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());){
                    //获得客户端的命令类型
                    int type = dataInputStream.readInt();
                    switch (type){
                          case TYPE_LOGIN:
                           System.out.printf("客户端 %s 执行登录\n",socket.getInetAddress());
                           handleLogin(dataInputStream,dataOutputStream);
                             break;
                        case TYPE_LIST:
                            System.out.printf("客户端 %s 执行查询\n",socket.getInetAddress());
                            handleListFiles(dataInputStream,dataOutputStream);
                            break;
                        case TYPE_UPLOAD:
                            System.out.printf("客户端 %s 执行上传\n",socket.getInetAddress());
                            handleUpload(dataInputStream,dataOutputStream);
                            break;
                        case TYPE_DOWNLOAD:
                            System.out.printf("客户端 %s 执行下载\n",socket.getInetAddress());
                            handleDownload(dataInputStream,dataOutputStream);
                            break;
                        case TYPE_DELETE:
                            System.out.printf("客户端 %s 执行删除\n",socket.getInetAddress());
                            handleDelete(dataInputStream,dataOutputStream);
                            break;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        new ServerV2().star();
    }

}
